#include "Subsystems/BlockBehaviors/SubsystemTrapdoorBlockBehavior.h"
#include "Managers/BlocksManager.h"
#include "Subsystems/SubsystemTerrain.h"
#include "Blocks/TrapdoorBlock.h"
#include "Blocks/WoodenTrapdoorBlock.h"
#include "Blocks/CellTrapdoorBlock.h"
#include "GameSingleton.h"

namespace PocketSurvival
{
    SubsystemTrapdoorBlockBehavior::SubsystemTrapdoorBlockBehavior()
    {
        m_handleBlocks.push_back(WoodenTrapdoorBlock::Index());
        m_handleBlocks.push_back(CellTrapdoorBlock::Index());
    }


    bool SubsystemTrapdoorBlockBehavior::onInteract(const TerrainRaycastResult &raycastResult, ComponentMiner *componentMiner)
    {
        const CellFace &cellFace = raycastResult.cellFace;

        int32_t cellValue = m_terrain->getCellValue(cellFace.point);
        int32_t num = Terrain::ExtractContents(cellValue);
        int32_t data = Terrain::ExtractData(cellValue);
        bool open = TrapdoorBlock::GetOpen(data);
        return openCloseDoor(cellFace.point.posX, cellFace.point.posY, cellFace.point.posZ, !open);

        // 下面是有电路才用的
        // if (num == 83 || !IsDoorElectricallyConnected(cellFace.X, cellFace.Y, cellFace.Z))
        // {
        // 	bool open = TrapdoorBlock.GetOpen(data);
        // 	return OpenCloseDoor(cellFace.X, cellFace.Y, cellFace.Z, !open);
        // }
        // return true;
    }
    void SubsystemTrapdoorBlockBehavior::onNeighborBlockChanged(int32_t x, int32_t y, int32_t z, int32_t neighborX, int32_t neighborY, int32_t neighborZ)
    {
        int32_t cellValue = m_terrain->getCellValue(x, y, z);
        int32_t num = Terrain::ExtractContents(cellValue);
        Block *obj = GameSingleton::blocksManager->blocks[num];
        int32_t data = Terrain::ExtractData(cellValue);
        if (dynamic_cast<TrapdoorBlock *>(obj) == nullptr)
        {
            return;
        }
        int32_t rotation = TrapdoorBlock::GetRotation(data);
        bool upsideDown = TrapdoorBlock::GetUpsideDown(data);
        bool flag = false;
        Point3 point = CellFace::FaceToPoint3(rotation);
        int32_t cellContents = m_terrain->getCellContents(x - point.posX, y - point.posY, z - point.posZ);
        flag |= (GameSingleton::blocksManager->blocks[cellContents]->IsTransparent == false);
        if (upsideDown == true)
        {
            int32_t cellContents2 = m_terrain->getCellContents(x, y + 1, z);
            flag |= (GameSingleton::blocksManager->blocks[cellContents2]->IsTransparent == false);
            int32_t cellContents3 = m_terrain->getCellContents(x - point.posX, y - point.posY + 1, z - point.posZ);
            flag |= (GameSingleton::blocksManager->blocks[cellContents3]->IsTransparent == false);
        }
        else
        {
            int32_t cellContents4 = m_terrain->getCellContents(x, y - 1, z);
            flag |= (GameSingleton::blocksManager->blocks[cellContents4]->IsTransparent == false);
            int32_t cellContents5 = m_terrain->getCellContents(x - point.posX, y - point.posY - 1, z - point.posZ);
            flag |= (GameSingleton::blocksManager->blocks[cellContents5]->IsTransparent == false);
        }
        if (flag == false)
        {
            m_terrain->destroyCell(0, x, y, z, 0, false);
        }
    }

    bool SubsystemTrapdoorBlockBehavior::openCloseDoor(int32_t x, int32_t y, int32_t z, bool open)
    {
        int32_t cellValue = m_terrain->getCellValue(x, y, z);
        int32_t num = Terrain::ExtractContents(cellValue);
        if (GameSingleton::blocksManager->blocks[num]->isBlock<TrapdoorBlock *>())
        {
            int32_t data = TrapdoorBlock::SetOpen(Terrain::ExtractData(cellValue), open);
            int32_t value = Terrain::ReplaceData(cellValue, data);
            m_terrain->changeCell(x, y, z, value);
            return true;
        }
        return false;
    }

    static const std::string subsystemName = "TrapDoorBlockBehavior";
    const std::string &SubsystemTrapdoorBlockBehavior::getName() const
    {
        return subsystemName;
    }
    void SubsystemTrapdoorBlockBehavior::update(float dt)
    {
    }
    void SubsystemTrapdoorBlockBehavior::load(const nlohmann::json &json)
    {
        m_terrain = GameSingleton::singletonPtr->getSingleton<SubsystemTerrain>();
    }
    void SubsystemTrapdoorBlockBehavior::save(nlohmann::json &json)
    {
    }
    void SubsystemTrapdoorBlockBehavior::saveToMsgJson(nlohmann::json &jsonData)
    {
    }
}